package com.liuyi.netty.im.test.im.client;

import com.liuyi.netty.im.commons.codes.LimProtocol;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.ScheduledFuture;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @author Mr.Fmy
 * @since 2022/1/19
 */
@Slf4j
public class HeartbeatHanlder extends ChannelDuplexHandler {

    private final Long initialDelay;
    private final Long period;
    private final TimeUnit timeUnit;
    private final LimProtocol heartbeat;

    private ScheduledFuture<?> scheduledFuture;

    public HeartbeatHanlder(Long initialDelay, Long period, LimProtocol heartbeat) {
        this(initialDelay, period, TimeUnit.SECONDS, heartbeat);
    }

    public HeartbeatHanlder(Long initialDelay, Long period, TimeUnit timeUnit, LimProtocol heartbeat) {
        this.initialDelay = initialDelay;
        this.period = period;
        this.timeUnit = timeUnit;
        this.heartbeat = heartbeat;
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        if (ctx.channel().isRegistered()) {
            this.initialize(ctx);
        }
        super.channelRegistered(ctx);
    }


    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        cancel();
        super.channelUnregistered(ctx);
    }

    private void initialize(ChannelHandlerContext ctx) {
        this.scheduledFuture = ctx.executor().scheduleAtFixedRate(() -> {
            ctx.channel().writeAndFlush(this.heartbeat);
        }, initialDelay, period, timeUnit);
    }

    private void cancel(){
        if (this.scheduledFuture != null){
            this.scheduledFuture.cancel(false);
            this.scheduledFuture = null;
        }
    }
}
